package vk
{
  import flash.errors.IOError;
  import flash.events.Event;
  import flash.events.EventDispatcher;
  import flash.events.IOErrorEvent;
  import mx.utils.ObjectUtil;
  import mx.utils.StringUtil;
  import Tools.Debug;
  import Tools.HtmlSpecials;
  import Tools.StringUtils;
  import vk.events.CustomEvent;
  import vk.events.SongProviderEvent;
  
  /**
   * ...
   * @author Roman Marchenko
   */
  public class SongProvider extends EventDispatcher
  {
    private var flashVars : Object; // stage.loaderInfo.parameters as Object;
    private var testMode : uint;
    private var VK : APIConnection;
    private var artist : String;
    private var title : String;
    private var errorCount : uint;
    
    private const MAX_ERROR_COUNT : uint = 5;
    
    public function SongProvider(params : Object)
    {
      errorCount = 0;
      testMode = 0;
      flashVars = params;
      if (!flashVars.api_id)
      {
        Debug.log("SongProvider: local testing mode");
        // -- Local testing settings
        // Note that the local testing settings are not under 
        // source control system due to security issues.
        flashVars['api_id'] = LocalTesting.API_ID;
        flashVars['viewer_id'] = LocalTesting.VIEWER_ID;
        flashVars['sid'] = LocalTesting.SID;
        flashVars['secret'] = LocalTesting.SECRET;
        // -- //
        testMode = 1;
      }
      
      VK = new APIConnection(flashVars);
      
      VK.addEventListener('onConnectionInit', function() : void
        {
          Debug.log("Connection initialized\n");
        });
      
      VK.addEventListener('onWindowBlur', function() : void
        {
          Debug.log("Window blur\n");
        });
      
      VK.addEventListener('onWindowFocus', function() : void
        {
          Debug.log("Window focus\n");
        });
      
      VK.addEventListener('onApplicationAdded', function() : void
        {
          Debug.log("Application added\n");
        });
      
      VK.addEventListener('onBalanceChanged', function(e : CustomEvent) : void
        {
          Debug.log("Balance changed: " + e.params[0] + "\n");
        });
      
      VK.addEventListener('onSettingsChanged', function(e : CustomEvent) : void
        {
          Debug.log("Settings changed: " + e.params[0] + "\n");
        });
      
      VK.addEventListener('onMerchantPaymentFail', function(e : CustomEvent) : void
        {
          Debug.log("Payment fail: " + e.params[0] + "\n");
        });
      
      VK.addEventListener('onMerchantPaymentSuccess', function(e : CustomEvent) : void
        {
          var msg : String = "Successfull payment.";
          if (e.params[0])
          {
            msg += " Order ID: " + e.params[0];
          }
          Debug.log(msg + "\n");
        });
      
      VK.addEventListener('onMerchantPaymentCancel', function() : void
        {
          Debug.log("Payment cancelled\n");
        });
    }
    
    public function findSong(artist : String, title : String) : void
    {
      this.artist = artist;
      this.title = title;
      
      VK.api('audio.search', {test_mode: testMode, q: artist + " " + title, count: 100}, onAudioSearch, onAudioSearchFail);
    }
    
    public function addAudio(aid : int, oid : int) : void
    {
      trace("SongProvider.addAudio: " + aid + ", " + oid);
      VK.api('audio.add', {test_mode: testMode, aid: aid, oid: oid}, onAudioAdd, onAudioAddFail);
    }
    
    private function onAudioSearch(data : Object) : void
    {
      if (0 == data[0])
      {
        Debug.log("SongProvider.onAudioSearch: Found nothing.");
        dispatchEvent(new SongProviderEvent(SongProviderEvent.SONG_NOT_FOUND, artist, title));
        return;
      }
      
      Debug.log("SongProvider.onAudioSearch");
      var arr: Array = new Array;
      for (var key : String in data)
      {
        if ("0" == key)
        {
          // skip length value
          continue;
        }
        
        //Debug.log("[" + key + "]:  " + data[key].artist + " - " + data[key].title);       
        var fartist : String = HtmlSpecials.decode(data[key].artist);
        fartist = StringUtil.trim(fartist);
        
        var ftitle : String = HtmlSpecials.decode(data[key].title);
        ftitle = StringUtil.trim(ftitle);
        
        var astr0:String = StringUtils.simplifyString(artist);
        var astr1:String = StringUtils.simplifyString(fartist);
        var tstr0:String = StringUtils.simplifyString(title);
        var tstr1:String = StringUtils.simplifyString(ftitle);
        if (0 == ObjectUtil.stringCompare(astr0, astr1, true) && 0 == ObjectUtil.stringCompare(tstr0, tstr1, true))
        {
          //Debug.log("SongProvider.onAudioSearch:  +[" + key + "]");
          //Debug.log("SongProvider.onAudioSearch: [" + key + "]:  " + data[key].artist + " - " + data[key].title + " (" + data[key].duration + " sec)" + ": " + data[key].url);
          // Add the song info to the array.
          arr.push(data[key]);
        }
      }
      
      if (0 == arr.length)
      {
        Debug.log("SongProvider.onAudioSearch: not found");
        dispatchEvent(new SongProviderEvent(SongProviderEvent.SONG_NOT_FOUND, artist, title));
      }
      else 
      {
        dispatchEvent(new SongProviderEvent(SongProviderEvent.SONG_FOUND, artist, title, arr));
      }
    }
    
    private function onAudioAdd(data : Object) : void
    {
      Debug.log("SongProvider.onAddAudio");
    }
    
    private function onAudioAddFail(data : Object) : void
    {
      Debug.log("SongProvider.onAudioAddFail");
      dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, (data.hasOwnProperty("error_msg") ? data.error_msg : data.toString())));
    }
  
    private function onAudioSearchFail(data : Object) : void
    {
      Debug.log("SongProvider.onAudioSearchFail: errorCount=" + errorCount);
      if (++errorCount < MAX_ERROR_COUNT)
      {
        // Try to re-send the request to make sure it's not an accident.
        findSong(artist, title);
        return;
      }
      
      dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, (data.hasOwnProperty("error_msg") ? data.error_msg : data.toString())));
    }
  
  }
}